﻿using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using System.Collections.ObjectModel;
using System.Linq;
using SQLDataTransferer.Model;
using System.Collections.Generic;

using Microsoft.SqlServer.Management.Smo;
using System.Data.SqlClient;

namespace SQLDataTransferer.ViewModel
{
    public abstract class SmoViewModelBase : BaseViewModel
    {
        #region Fields

        RelayCommand _serversRefreshCommand;
        RelayCommand _databasesRefreshCommand;

        #endregion

        #region Constructor(s)

        public SmoViewModelBase(string displayName, System.Globalization.CultureInfo culture, Dispatcher dispatcher, Window main)
        {
            base.CurrentCulture = culture;
            base.DisplayName = displayName; //TODO/ TranslationManager.Translate(displayName, culture);
            base.DispatcherObject = dispatcher;
            base.MainWindow = main;

            //TODO:
            //this.Servers = new ObservableCollection<Model.SqlInstance>();
            //this.Databases = new ObservableCollection<Database>();
        }

        #endregion

        #region Properties

        RadioButtonOptions _currentOption = RadioButtonOptions.Windows; //this is the default option as selected
        /// <summary>
        /// Used as workaround for the radiobuttons databinding
        /// </summary>
        public RadioButtonOptions CurrentOption
        {
            get { return this._currentOption; }
            set
            {
                this._currentOption = value;

                this.OnPropertyChanged("CurrentOption");
            }
        }

        public IList<SqlInstance> Servers { get; set; }

        public IList<Database> Databases { get; set; }

        public SqlInstance SelectedServer { get; set; }

        public Database SelectedDb { get; set; }

        #region Commands

        public ICommand ServersRefreshCommand
        {
            get
            {
                if (this._serversRefreshCommand == null)
                    this._serversRefreshCommand = new RelayCommand((o) => this.OnServersRefresh(o));

                return this._serversRefreshCommand;
            }
        }

        public ICommand DatabasesRefreshCommand
        {
            get
            {
                if (this._databasesRefreshCommand == null)
                    this._databasesRefreshCommand = new RelayCommand((o) => this.OnDatabasesRefresh());

                return this._databasesRefreshCommand;
            }
        }

        #endregion

        #endregion

        #region Methods

        /// <summary>
        /// Exectutes the actual code for retrieving/refreching a list of server instances
        /// </summary>
        /// <returns></returns>
        protected void OnServersRefresh(object obj)
        {
            this.RunTaskDialog("Refreshing Servers ...",
                () =>
                {
                    this.Servers = this.LoadServers();
                    this.OnPropertyChanged("Servers");
                });
        }

        protected IList<SqlInstance> LoadServers()
        {
            // Get current host name from registry
            var hostName = Common.Utils.RegistryUtils.GetRegistryKeyValueFromLocalMachine(
                                Properties.Settings.Default.RegistryKeyNameComputer,
                                Properties.Settings.Default.RegistryKeyValueComputer);

            // Get current installed sql instances from registry
            var instances = Common.Utils.RegistryUtils.GetRegistryKeyValuesFromLocalMachine(
                                        Properties.Settings.Default.RegistryKeyNameSQLServers,
                                       Properties.Settings.Default.RegistryKeyValueSQLServers);

            IList<SqlInstance> collection = new List<SqlInstance>();

            Array.Sort(instances);
            if (instances != null)
                foreach (string instance in instances)
                    collection.Add(new Model.SqlInstance(hostName, instance));

            return collection;
        }       

        /// <summary>
        /// Exectutes the actual code for retrieving/refreching a list of database from the current selected db server
        /// </summary>
        /// <returns></returns>
        protected void OnDatabasesRefresh()
        {
            this.RunTaskDialog("Refreshing Databases ...",
                () =>
                {
                    this.Databases = this.LoadDatabases(this.SelectedServer, this.CurrentOption == RadioButtonOptions.Windows);
                    this.OnPropertyChanged("Databases");
                });
        }

        protected IList<Database> LoadDatabases(SqlInstance item, bool integrated = true)
        {
            if (item == null)
                throw new Exception("Server not selected");

            Server server = null;
            try
            {
                server = new Server(
                   new Microsoft.SqlServer.Management.Common.ServerConnection(
                       new System.Data.SqlClient.SqlConnection(
                           new SqlConnectionStringBuilder()
                           {
                               DataSource = item.FullName,
                               IntegratedSecurity = integrated
                           }.ConnectionString)));

                //Try to connect, if fails it throws an SQL Exception
                server.ConnectionContext.Connect();

                return server.Databases.OfType<Database>().ToList();
            }
            finally
            {
                if (server != null &&
                    server.ConnectionContext.IsOpen)
                    server.ConnectionContext.Disconnect();
            }
        }

        #endregion
    }
}
